package com.sky.handler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * MyBatis自定义类型处理器
 * 用于实现List<String>类与数据库中JSON字符串的自动转换
 */
//声明该处理器映射的Java类型为List.class
@MappedTypes(List.class)
public class ListTypeHandler extends BaseTypeHandler<List<String>> {

    //Jackson的对象映射器，用于JSON序列化和反序列化
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 当Java对象写入数据库时调用
     * 将List<String>转换为JSON字符串存入数据库
     * @param ps            PreparedStatement对象
     * @param i             参数索引
     * @param parameter     要转换的List对象
     * @param jdbcType      JDBC数据类型
     * @throws SQLException SQL异常
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException {
        try {
            //将List对象序列化为JSON字符串，设置到SQL语句中
            ps.setString(i, objectMapper.writeValueAsString(parameter));
        } catch (JsonProcessingException e) {
            throw new SQLException("Error converting List to JSON", e);
        }
    }

    /**
     * 从ResultSet中按列名获取数据时调用
     * 将数据库中的JSON字符串转换为List
     * @param rs             结果集
     * @param columnName     列名
     * @return               转换后的List对象
     * @throws SQLException  SQL异常
     */
    @Override
    public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return parseJSON(rs.getString(columnName));
    }

    /**
     * 从ResultSet中按列索引获取数据时调用
     * 将数据库中的JSON字符串转换为List
     * @param rs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return parseJSON(rs.getString(columnIndex));
    }

    /**
     * 从CallableStatement中按列索引获取数据时调用
     * 将数据库中的JSON字符串转换为List
     * @param cs
     * @param columnIndex
     * @return
     * @throws SQLException
     */
    @Override
    public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return parseJSON(cs.getString(columnIndex));
    }

    /**
     * 私有工具方法，将JSON字符串反序列化为List<String>
     *
     * @param json 数据库中的JSON字符串
     * @return 转换后的List<String>对象，若json为null则返回null
     * @throws SQLException SQL异常
     */
    private List<String> parseJSON(String json) throws SQLException {
        try {
            if (json == null) {
                return null;
            }
            //将JSON字符串反序列化为List对象
            return objectMapper.readValue(json, List.class);
        } catch (JsonProcessingException e) {
            throw new SQLException("Error parsing JSON to List", e);
        }
    }
}